<?php

namespace common\components\wechat;

use Yii;
use yii\helpers\ArrayHelper;
use yii\base\Exception;
use common\components\wechat\lib\WxPayApi;
use common\components\wechat\data\WxPayOrderQuery;
use common\components\wechat\data\WxPayCloseOrder;
use common\components\wechat\payment\PayNotifyCallBack;
use common\components\wechat\models\JsApiPay;
use common\components\wechat\payment\MicroPay;
use common\components\wechat\payment\NativePay;

/**
 * 微支付扩展
 * @author emhome
 */
class WechatPayment extends \yii\base\Widget {

    /**
     * @var string the default field class name when calling [[field()]] to create a new field.
     * @see fieldConfig
     */
    public $transportClass = JsApiPay::class;
    public $appid;
    public $appsecret;
    public $mch_id;
    public $key;

    /**
     * @var array|\Closure the default configuration used by [[field()]] when creating a new field object.
     * @see transportClass
     */
    public $transportConfig = [];

    /**
     * 支付参数配置
     * @see transportClass
     */
    public $paymentConfig = [];

    /**
     * @inheritdoc
     * @throws InvalidConfigException
     */
    public function init() {
        parent::init();
        if (isset(Yii::$app->params['wechat'])) {
            $wconfig = Yii::$app->params['wechat'];
            if (empty($this->paymentConfig)) {
                $this->paymentConfig = [
                    'appid' => $wconfig['appId'],
                    'appsecret' => $wconfig['appSecret'],
                    'mch_id' => $wconfig['mch_id'],
                    'key' => $wconfig['key'],
                    'notify_url' => $wconfig['notify_url'],
                ];
            }
        }
    }

    /**
     * Generates a form field.
     */
    public function transport($options = []) {
        if (!isset($this->transportConfig['class'])) {
            $this->transportConfig['class'] = $this->transportClass;
        }
        return Yii::createObject(ArrayHelper::merge($this->transportConfig, $options));
    }

    /**
     * Generates a form field.
     */
    public function payment($options = []) {
        if (!isset($options['class'])) {
            $options['class'] = $this->transportClass;
        }
        return Yii::createObject(ArrayHelper::merge($options, [
            'model' => $this,
        ]));
    }

    public function orderQuery($out_trade_no = false, $transaction_id = false) {
        $input = new WxPayOrderQuery();
        //设置商户系统内部的订单号,32个字符内、可包含字母, 其他说明见商户订单号
        if ($transaction_id != false) {
            $input->SetTransaction_id($transaction_id);
        } else {
            $input->SetOut_trade_no($out_trade_no);
        }
        return WxPayApi::orderQuery($input);
    }

    public function closeOrder($trade_no) {
        $input = new WxPayCloseOrder();
        $input->SetOut_trade_no($trade_no);

        return WxPayApi::closeOrder($input);
    }

    public function notice() {
        return new PayNotifyCallBack();
    }

    public function response($data) {
        return $data;
    }

    /**
     * 获取jsapi支付的参数
     * @param array $UnifiedOrderResult 统一支付接口返回的数据
     * @throws WxPayException
     * 
     * @return json数据，可直接填入js函数作为参数
     */
    public function getJsApiParameters($UnifiedOrderResult) {
        static::invokeLog('UnifiedOrderResult', $UnifiedOrderResult);
        if (ArrayHelper::getValue($UnifiedOrderResult, 'return_code') == 'FAIL') {
            throw new Exception('' . ArrayHelper::getValue($UnifiedOrderResult, 'return_msg'));
        }
        $appId = ArrayHelper::getValue($UnifiedOrderResult, 'appid');
        $prepayId = ArrayHelper::getValue($UnifiedOrderResult, 'prepay_id');
        if (!$appId || !$prepayId) {
            throw new Exception('参数错误' . ArrayHelper::getValue($UnifiedOrderResult, 'return_msg'));
        }

        $jsapi = new JsApiPay([
            'model' => $this
        ]);
        $jsapi->attributes = [
            'appId' => $appId,
            'timeStamp' => strval(time()),
            'nonceStr' => Yii::$app->security->generateRandomString(32),
            'package' => "prepay_id=" . $prepayId,
            'signType' => 'MD5',
        ];
        $jsapi->generateSign($jsapi->paySign);

        static::invokeLog('UnifiedOrderResult', $jsapi->attributes);

        return $jsapi->attributes;
    }

    /**
     * 记录处理日志
     */
    public static function invokeLog($prefix, $content) {
        $message = \yii\helpers\Inflector::id2camel($prefix) . ":";
        $message .= "\n" . \yii\helpers\VarDumper::export($content);
        Yii::error("\n" . $message, 'payment');
    }

}
